; *****************************************************************
; INT13h, AH=42h - READ SECTOR EXTENDED
; Part of Reindeer OS boot loader
;
; Copyrights 2011 Michal Saman, m.saman@designplus.cz.
; This source code is release under the Apache License 2.0.
; http://www.apache.org/licenses/LICENSE-2.0
; *****************************************************************

re_debug_mode			db		0
re_msg_read_failure		db		13, 10, "INT13h,AL=42h - medium read failed.", 13, 10, "Error code: ", 0
re_msg_progress			db		".", 0
re_msg_LBA				db		"LBA to read: ", 0
re_msg_Drive			db		"Drive to read: ", 0
re_msg_SectorsCount		db		"Sectors count: ", 0
re_msg_debug			db		13,10,"** READ SECTOR EXT debug **",13,10,0
re_msg_buff_seg			db		"DAP buffer seg: ", 0
re_msg_buff_off			db		"DAP buffer off: ", 0

okok:
struc dap_t
	.dap_size			resb 1
	.res				resb 1
	.sc					resw 1
	.buffer				resd 1
	.lba_l				resd 1
	.lba_h				resd 1
endstruc

dap:
istruc dap_t
	at dap_t.dap_size,  db	0x10	; size of DAP = 16 = 10h
	at dap_t.res,		db	0		; unused, should be zero
	at dap_t.sc,		dw	0		; number of sectors to be read
	at dap_t.buffer,	dd	0		; segment:offset pointer to the memory buffer to which sectors will be transferred
	at dap_t.lba_l,		dd	0		; absolute number of the start of the sectors to be read (high part)
	at dap_t.lba_h,		dd	0		; absolute number of the start of the sectors to be read (low part)
iend

; *******************************************************************
; * Read Sector Extended (function)								 	*
; * -------------------------------									*
; * DS:SI		segment:offset pointer to the DAP					*
; * 																*
; * Input:															*
; * BX		LBA address of sector to read							*
; * DL		drive index (e.g. 1st HDD = 80h)						*
; * CX		count of sectors to read								*
; * [re_debug_mode]		debug mode enabled (0/1)					*
; *******************************************************************
read_sector_ext:
	push		di
	push		ax
	push		si
	pushf
	; debug start
	cmp			BYTE [re_debug_mode], 0			; is debug enabled???
	je			.debugSkip
.debugStart:
	mov			si, re_msg_debug
	call		Puts16
	mov			si, re_msg_LBA
	call		Puts16
	mov			ax, bx
	call		PrintRegister16
	mov			si, re_msg_Drive
	call		Puts16
	xor			ax, ax
	mov			al, dl
	call		PrintRegister16
	mov			si, re_msg_SectorsCount
	call		Puts16
	mov			ax, cx
	call		PrintRegister16
	mov			si, re_msg_buff_seg
	call		Puts16
	mov			ax, WORD [dap + dap_t.buffer + 2]
	call		PrintRegister16
	mov			si, re_msg_buff_off
	call		Puts16
	mov			ax, WORD [dap + dap_t.buffer]
	call		PrintRegister16
	xor			ax, ax
	mov			ah, 0x00						; set function id
	int			0x16							; wait for keypress
	cmp			BYTE [re_debug_mode], 2			; final report??
	je			.END							; if yes, go to end
	; debug end
.debugSkip:
	xor			di, di
.read_loop:
	mov			si, dap												; location of DAP structure
	mov			WORD [dap + dap_t.sc], 1							; count of sectors to read
	mov			WORD [dap + dap_t.buffer + 2], READ_BUFF_SEG		; read buffer segment
	mov			ax, WORD [dap + dap_t.buffer + 2]
	mov			ax, di
	push		dx
	mul			WORD [iso_sector_size]
	pop			dx
	add			ax, READ_BUFF_OFF
	mov			WORD [dap + dap_t.buffer], ax						; read buffer offset
	mov			WORD [dap + dap_t.lba_l], bx						; first sector to read (low bits)
	mov			WORD [dap + dap_t.lba_h], 0							; first sector to read (high bits)
	xor			ax, ax												; clear ax register
	mov			ah, 0x42											; function number
	int			0x13												; call bios over interrupt
	jnc			.OK
	.FAILURE:
		mov		si, re_msg_read_failure
		call	Puts16
		call	PrintRegister16
		mov		BYTE [re_debug_mode], 2
		jmp		.debugStart
		jmp		.END
	.OK:
		mov		si, re_msg_progress
		call	Puts16
		inc		di
		cmp		di, cx
		je		.END
		inc		bx
		jmp		.read_loop
	.END:
		mov		BYTE [re_debug_mode], 0				; disable debug mode
		popf
		pop		si
		pop		ax
		pop		di
		ret

; ----------------------------------
